109. ポストプロセッシング: 3.ブルーム効果

Framebuffer と uniformTexture を使用して、明るい部分がじわっと光るブルーム効果を実装します。

p5.js 2.0 WebGL p5.strands Shader GLSL
Learning Tutorial

ブルーム (Bloom)

ポストプロセッシングにおけるブルームは、画像の中の非常に明るい部分が周囲に滲み出し、光っているように見せるエフェクトです。これにより、高価なライティング計算を行うことなく、シーンの特定の場所から光が放出されているような感覚を生み出せます。

ブルームの仕組みは単純化すると以下のようになります:

  1. 画像をぼかしたものを作成する
  2. 特定のしきい値(明るさ)以上の部分のみを抽出し、元の画像に加算する

p5.js には filter(BLUR) が用意されているので、これを活用しましょう。ただし、ぼかす前の元の画像を保持しておくために、p5.Framebuffer オブジェクトを使用する必要があります。

フレームバッファの使用

まず、setup()createFramebuffer() を呼び出し、レンダリングターゲットを作成します。

let originalImage;

async function setup() {
  // ...
  originalImage = createFramebuffer();
}

draw() 内では、描画内容を originalImage に保存し、それを画面に描画した後に filter(BLUR) を適用します。

function draw() {
  originalImage.begin();
  // ... 描画処理 ...
  originalImage.end();

  imageMode(CENTER);
  image(originalImage, 0, 0);

  // この値を変更すると、ブルームの広がりが変化します
  filter(BLUR, 15);
}

ブルームシェーダーの実装

この時点では画面全体がぼけているだけですが、ここに uniformTexture として元の画像を渡すカスタムシェーダーを適用します。

function bloomCallback() {
  const ogImage = uniformTexture(() => originalImage);

  getColor((input, canvasContent) => {
    // ぼけたテクスチャと元のテクスチャを取得します
    const blurred = getTexture(canvasContent, input.texCoord);
    const original = getTexture(ogImage, input.texCoord);

    const intensity = max(original, 0.3) * 1.5;
    // ぼけた画像を元の画像に重ね合わせます
    const bloom = original + blurred * intensity;
    return [bloom.rgb, 1];
  });
}

スケッチのソースコードを見てみましょう:

let bloomShader;
let originalImage;

function bloomCallback() {
  const preBlur = uniformTexture(() => originalImage);

  getColor((input, canvasContent) => {
    const blurred = getTexture(canvasContent, input.texCoord);
    const original = getTexture(preBlur, input.texCoord);

    const intensity = max(original, 0.2) * 8;

    const bloom = original + blurred * intensity;
    return [bloom.rgb, 1];
  });
}

async function setup() {
  createCanvas(400, 400, WEBGL);
  pixelDensity(1);
  originalImage = createFramebuffer();
  bloomShader = baseFilterShader().modify(bloomCallback);
}

function draw() {
  // ぼかす前に保存しておくために、描画内容を
  // Framebuffer に書き込みます
  originalImage.begin();
  background(0);
  rotateY(millis() / 1000);
  fill(40, 120, 255);
  box(80);
  originalImage.end();

  imageMode(CENTER);
  image(originalImage, 0, 0);

  // この値を変更すると、ブルームの広がりが変化します
  filter(BLUR, 20);
  filter(bloomShader);
}

スウィズリング (Swizzling)

GLSL(そして p5.strands)には、スウィズリング (Swizzling) という強力な機能があります。これは、ベクトルのコンポーネントを自由な順序で選択して、新しいベクトルを構築できる機能です。

.rgba.xyzw.stpq(テクスチャ用)のいずれかの組み合わせを使用して、例えば col.grg と書くと [col.g, col.g, col.r] という新しいベクトルが作られます。

HINT
inputs.color = [col.ggr, 1] のように戻り値をスウィズリングして、面白い色の変化を試してみてください。

License

Original URL: https://beta.p5js.org/tutorials/intro-to-p5-strands/

License: MIT License

Copyright (c) 2015-present p5.js contributors & The Processing Foundation